<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#FFF"><meta name="baidu-site-verification" content="code-DvHFUp3jdk"><meta name="baidu-site-verification" content="code-eHnRZZHAeP"><meta name="baidu-site-verification" content="code-EmlZBboqEW"><meta name="baidu-site-verification" content="code-Hf9ZXEHZ41"><meta name="360-site-verification" content="941073b91e9afaf02748ba000ba47e80"><meta name="360-site-verification" content="010bd45f0d523ce46f298dd597ef0289"><meta name="sogou_site_verification" content="hlLPNfmIjv"><meta name="sogou_site_verification" content="y3La2dTB20"><meta name="msvalidate.01" content="03829B28CC46A7AA4B5503897F475BA1"><script>!function(){var s="https://s.ssl.qhres2.com/ssl/ab77b6ea7f3fbf79.js";document.write('<script src="'+s+'" id="sozz"><\/script>')}()</script><script>!function(t,e,c,n,r,a,s){t[c]=t[c]||function(){(t[c].q=t[c].q||[]).push(arguments)},a=e.createElement(n),a.async=1,a.src="https://www.clarity.ms/tag/"+r+"?ref=bwt",s=e.getElementsByTagName(n)[0],s.parentNode.insertBefore(a,s)}(window,document,"clarity","script","8xwpfccwj2")</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?1d318b0509ca0909017253ed6f659ae4";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?aea6c1471d6299bdd1c87a0836f18675";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?498ca413655655a62058d6b5d7c62786";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?e19e8161e13f718806b79f49240583b4";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png"><link rel="icon" type="image/ico" sizes="32x32" href="/images/favicon.ico"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="google-site-verification" content="UA-139249935-1"><meta name="baidu-site-verification" content="cOtBu9CtTEIuwJeN"><link rel="alternate" type="application/rss+xml" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/rss.xml"><link rel="alternate" type="application/atom+xml" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/atom.xml"><link rel="alternate" type="application/json" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/feed.json"><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Mulish:300,300italic,400,400italic,700,700italic%7CFredericka%20the%20Great:300,300italic,400,400italic,700,700italic%7CNoto%20Serif%20JP:300,300italic,400,400italic,700,700italic%7CNoto%20Serif%20SC:300,300italic,400,400italic,700,700italic%7CInconsolata:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext"><link rel="stylesheet" href="/css/app.css?v=0.2.5"><meta name="keywords" content="编程,Shiny入门系列"><link rel="canonical" href="https://liaochenlanruo.gitee.io/post/6685.html"><title>Shiny从入门到入定——7-图形 - IT | ResearchGo = 了尘兰若的小坑 = liaochenlanruo</title><meta name="generator" content="Hexo 5.4.0"></head><body itemscope itemtype="http://schema.org/WebPage"><div id="loading"><div class="cat"><div class="body"></div><div class="head"><div class="face"></div></div><div class="foot"><div class="tummy-end"></div><div class="bottom"></div><div class="legs left"></div><div class="legs right"></div></div><div class="paw"><div class="hands left"></div><div class="hands right"></div></div></div></div><div id="container"><header id="header" itemscope itemtype="http://schema.org/WPHeader"><div class="inner"><div id="brand"><div class="pjax"><h1 itemprop="name headline">Shiny从入门到入定——7-图形</h1><div class="meta"><span class="item" title="Created: 2024-01-26 22:09:43"><span class="icon"><i class="ic i-calendar"></i> </span><span class="text">Posted on</span> <time itemprop="dateCreated datePublished" datetime="2024-01-26T22:09:43+08:00">2024-01-26</time> </span><span class="item" title="Symbols count in article"><span class="icon"><i class="ic i-pen"></i> </span><span class="text">Symbols count in article</span> <span>8.5k</span> <span class="text">words</span> </span><span class="item" title="Reading time"><span class="icon"><i class="ic i-clock"></i> </span><span class="text">Reading time</span> <span>8 mins.</span></span></div></div></div><nav id="nav"><div class="inner"><div class="toggle"><div class="lines" aria-label="Toggle navigation bar"><span class="line"></span> <span class="line"></span> <span class="line"></span></div></div><ul class="menu"><li class="item title"><a href="/" rel="start">ResearchGo</a></li></ul><ul class="right"><li class="item theme"><i class="ic i-sun"></i></li><li class="item search"><i class="ic i-search"></i></li></ul></div></nav></div><div id="imgs" class="pjax"><img src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/custom/bgs/thumb_207.webp"></div></header><div id="waves"><svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"/></defs><g class="parallax"><use xlink:href="#gentle-wave" x="48" y="0"/><use xlink:href="#gentle-wave" x="48" y="3"/><use xlink:href="#gentle-wave" x="48" y="5"/><use xlink:href="#gentle-wave" x="48" y="7"/></g></svg></div><main><div class="inner"><div id="main" class="pjax"><div class="article wrap"><div class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList"><i class="ic i-home"></i> <span><a href="/">Home</a></span><i class="ic i-angle-right"></i> <span class="current" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a href="/categories/IT/" itemprop="item" rel="index" title="In IT"><span itemprop="name">IT</span></a><meta itemprop="position" content="1"></span></div><article itemscope itemtype="http://schema.org/Article" class="post block" lang="en"><link itemprop="mainEntityOfPage" href="https://liaochenlanruo.gitee.io/post/6685.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/images/head.jpg"><meta itemprop="name" content="Hualin Liu"><meta itemprop="description" content="liaochenlanruo, 分享微生物生物信息学分析方法，欢迎加入QQ群交流945751012，不接受群内广告！"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="了尘兰若的小坑"></span><div class="body md" itemprop="articleBody"><div class="gallery" itemscope itemtype="http://schema.org/ImageGallery"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/custom/bgs/thumb_207.webp" itemprop="contentUrl"></div><h1 id="7-图形"><a class="anchor" href="#7-图形">#</a> 7 图形</h1><ul><li>第 7 章向您展示了如何向绘图添加直接交互以及如何显示以其他方式生成的图像。</li></ul><p>我们在第 2 章中简要讨论了 <a href="">renderPlot()</a> ; 它是在应用程序中显示图形的强大工具。本章将向您展示如何充分利用它来创建交互式绘图，即响应鼠标事件的绘图。您还将学习一些其他有用的技术，包括制作具有动态宽度和高度的绘图以及使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vcmVuZGVySW1hZ2UuaHRtbA==">renderImage()</span> 显示图像。</p><p>在本章中，我们将需要 ggplot2 和 Shiny，因为我们将其用于大多数图形的绘制。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>library<span class="token punctuation">(</span>shiny<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre>library<span class="token punctuation">(</span>ggplot2<span class="token punctuation">)</span></pre></td></tr></table></figure><h2 id="71-交互性"><a class="anchor" href="#71-交互性">#</a> 7.1 交互性</h2><p><span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vcGxvdE91dHB1dC5odG1s">plotOutput()</span> 最酷的一点是，它不仅可以作为显示绘图的输出，还可以作为响应指针事件的输入。这允许您创建交互式图形，用户直接与绘图上的数据进行交互。交互式图形是一种强大的工具，具有广泛的应用范围。我没有空间向你展示所有的可能性，所以在这里我将重点介绍基础知识，然后向你指出资源以了解更多信息。</p><h3 id="711-基础知识"><a class="anchor" href="#711-基础知识">#</a> 7.1.1 基础知识</h3><p>绘图可以响应四种不同的鼠标事件： <code>click</code> 、 <code>dblclick</code> （双击）、 <code>hover</code> （当鼠标在同一位置停留一段时间时）和 <code>brush</code> （矩形选择工具）。要将这些事件转换为 Shiny 的输入，您需要为相应的 <code>plotOutput()</code> 参数提供一个字符串，例如 <code>plotOutput(&quot;plot&quot;, click = &quot;plot_click&quot;)</code> 。这将创建一个 <code>input$plot_click</code> ，您可以使用它来处理鼠标在绘图上的单击。</p><p>下面是一个非常简单的处理鼠标单击的示例。我们注册 <code>plot_click</code> 输入，然后使用鼠标单击的坐标更新输出。图 7.1 显示了结果。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> click <span class="token operator">=</span> <span class="token string">"plot_click"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  verbatimTextOutput<span class="token punctuation">(</span><span class="token string">"info"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre></pre></td></tr><tr><td data-num="6"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="7"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    plot<span class="token punctuation">(</span>mtcars<span class="token operator">$</span>wt<span class="token punctuation">,</span> mtcars<span class="token operator">$</span>mpg<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre></pre></td></tr><tr><td data-num="11"></td><td><pre>  output<span class="token operator">$</span>info <span class="token operator">&lt;-</span> renderPrint<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="12"></td><td><pre>    req<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>    x <span class="token operator">&lt;-</span> round<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token operator">$</span>x<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="14"></td><td><pre>    y <span class="token operator">&lt;-</span> round<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token operator">$</span>y<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="15"></td><td><pre>    cat<span class="token punctuation">(</span><span class="token string">"["</span><span class="token punctuation">,</span> x<span class="token punctuation">,</span> <span class="token string">", "</span><span class="token punctuation">,</span> y<span class="token punctuation">,</span> <span class="token string">"]"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="16"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/8e3506131c2af7ac0ddd07569f277dd03e05ff0e/f836c/images/action-graphics/click.png" alt="图 7.1 单击左上角的点可更新打印的坐标 查看演示实例 https://hadley.shinyapps.io/ms-click 。"></p><p>（请注意使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vcmVxLmh0bWw=">req()</span> ，以确保应用在第一次单击之前不会执行任何操作，且坐标以 <code>wt</code> 和 <code>mpg</code> 变量表示。</p><p>以下各节更详细地介绍了这些事件。我们将从点击事件开始，然后简要讨论密切相关的 <code>dblclick</code> 和 <code>hover</code> 。然后，您将了解 <code>brush</code> 事件，该事件提供了一个矩形 <code>brush</code> ，由其四个边（ <code>xmin</code> ， <code>xmax</code> ， <code>ymin</code> 和 <code>ymax</code> 定义。然后，我将举几个示例，使用动作结果更新绘图，然后讨论 Shiny 中交互式图形的一些局限性。</p><h3 id="712-点击"><a class="anchor" href="#712-点击">#</a> 7.1.2 点击</h3><p>点事件返回一个相对丰富的列表，其中包含大量信息。最重要的组件是 <code>x</code> 和 <code>y</code> ，它们在数据坐标中给出事件的位置。但我不打算谈论这种数据结构，因为你只在相对罕见的情况下需要（如果你确实想要细节，请在 Shiny 图库中使用这个应用程序）。相反，您将使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vYnJ1c2hlZFBvaW50cy5odG1s">nearPoints()</span> 帮助程序，该帮助程序返回一个数据框，其中包含单击附近的行，并处理一堆繁琐的细节。</p><p>下面是 <code>nearPoints()</code> 运行的简单示例，其中显示了有关事件附近点的数据表。图 7.2 显示了该应用的屏幕截图。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> click <span class="token operator">=</span> <span class="token string">"plot_click"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  tableOutput<span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    plot<span class="token punctuation">(</span>mtcars<span class="token operator">$</span>wt<span class="token punctuation">,</span> mtcars<span class="token operator">$</span>mpg<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  </pre></td></tr><tr><td data-num="10"></td><td><pre>  output<span class="token operator">$</span>data <span class="token operator">&lt;-</span> renderTable<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    nearPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_click<span class="token punctuation">,</span> xvar <span class="token operator">=</span> <span class="token string">"wt"</span><span class="token punctuation">,</span> yvar <span class="token operator">=</span> <span class="token string">"mpg"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/7c89122f2822dac1dbe5640e4aab942bebb46ef9/8d5d6/images/action-graphics/nearpoints.png" alt="图 7.2 nearPoints() 将绘图坐标转换为数据行，从而可以轻松显示您单击的点的基础数据 查看实例 https://hadley.shinyapps.io/ms-nearPoints 。"></p><p>在这里，我们给出 <code>nearPoints()</code> 四个参数：作为绘图基础的数据框、输入事件和轴上变量的名称。如果使用 <code>ggplot2</code> ，则只需提供前两个参数，因为 <code>xvar</code> 和 <code>yvar</code> 可以从绘图数据结构中自动插补。出于这个原因，我将在本章的其余部分使用 <code>ggplot2</code> 。下面是使用 <code>ggplot2</code> 重新实现的上一个示例：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> click <span class="token operator">=</span> <span class="token string">"plot_click"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  tableOutput<span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    ggplot<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> aes<span class="token punctuation">(</span>wt<span class="token punctuation">,</span> mpg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> geom_point<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  </pre></td></tr><tr><td data-num="10"></td><td><pre>  output<span class="token operator">$</span>data <span class="token operator">&lt;-</span> renderTable<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    req<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>    nearPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="14"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p>您可能想知道 <code>nearPoints()</code> 究竟返回了什么。这是使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3IvYmFzZS9icm93c2VyLmh0bWw=">browser()</span> 的好地方，我们在 Section 5.2.3 中讨论过：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre><span class="token ellipsis">...</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  output<span class="token operator">$</span>data <span class="token operator">&lt;-</span> renderTable<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    req<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    browser<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    nearPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token ellipsis">...</span></pre></td></tr></table></figure><p>现在，在我启动应用程序并单击一个点后，我被放入交互式调试器，在那里我可以运行 <code>nearPoints()</code> 并查看它返回的内容：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>nearPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_click<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre><span class="token comment">#>             mpg cyl disp hp drat   wt  qsec vs am gear carb</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token comment">#> Datsun 710 22.8   4  108 93 3.85 2.32 18.61  1  1    4    1</span></pre></td></tr></table></figure><p>使用 <code>nearPoints()</code> 的另一种方法是使用 <code>allRows = TRUE</code> 和 <code>addDist = TRUE</code> 。这将返回包含两个新列的原始数据框：</p><ul><li><code>dist_</code> 给出行和事件之间的距离（以像素为单位）。</li><li><code>selected_</code> 表示它是否靠近 click 事件（即它是否是 <code>allRows = FALSE</code> ) 时返回的行。</li></ul><p>我们稍后会看到一个例子。</p><h3 id="713-其他点事件"><a class="anchor" href="#713-其他点事件">#</a> 7.1.3 其他点事件</h3><p>同样的方法对 <code>click</code> 、 <code>dblclick</code> 和 <code>hover</code> 同样有效：只需更改参数的名称。如果需要，可以通过提供 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vY2xpY2tPcHRzLmh0bWw=">clickOps()</span>、<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vY2xpY2tPcHRzLmh0bWw=">dblclickOps()</span> 或 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vY2xpY2tPcHRzLmh0bWw=">hoverOps()</span> 而不是给出输入 id 的字符串来获得对事件的额外控制。这些很少需要，所以我这里不讨论它们；请参阅文档以获取详细信息。</p><p>您可以在一个图上使用多种交互类型。只需确保向用户解释他们可以做什么：使用鼠标事件与应用程序交互的一个缺点是它们不能立即被发现。</p><h3 id="714-刷涂brushing"><a class="anchor" href="#714-刷涂brushing">#</a> 7.1.4 刷涂（Brushing）</h3><p>在绘图上选择点的另一种方法是使用画笔，画笔是由四个边定义的矩形选择。在 Shiny 中，一旦掌握了 <code>click</code> 和 <code>nearPoints()</code> ，使用画笔就非常简单：只需切换到 <code>brush</code> 参数和 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vYnJ1c2hlZFBvaW50cy5odG1s">brushedPoints()</span> 辅助函数。</p><p>这是另一个简单的例子，显示了画笔选择了哪些点。图 7.3 显示了结果。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> brush <span class="token operator">=</span> <span class="token string">"plot_brush"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  tableOutput<span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    ggplot<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> aes<span class="token punctuation">(</span>wt<span class="token punctuation">,</span> mpg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> geom_point<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  </pre></td></tr><tr><td data-num="10"></td><td><pre>  output<span class="token operator">$</span>data <span class="token operator">&lt;-</span> renderTable<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    brushedPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_brush<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/72c746e68848220485ba12c028382dd0de8a3a00/fc713/images/action-graphics/brushedpoints.png" alt="图 7.3 设置 brush 参数为用户提供了一个可拖动的“画笔”。在此应用程序中，画笔下方的点显示在表格中。在 https://hadley.shinyapps.io/ms-brushedPoints 上查看演示。"></p><p>使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vYnJ1c2hPcHRzLmh0bWw=">brushOptions()</span> 控制颜色（填充和描边），或将刷涂限制为 <code>direction = &quot;x&quot;</code> 或 <code>&quot;y&quot;</code> 的单个维度（例如，用于刷涂时间序列）。</p><h3 id="715-修改绘图"><a class="anchor" href="#715-修改绘图">#</a> 7.1.5 修改绘图</h3><p>到目前为止，我们已经展示了交互的结果。但是，交互的真正魅力在于，当你显示你正在交互的同一图中的变化时。不幸的是，这需要你尚未学过的先进反应技术：<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vcmVhY3RpdmVWYWwuaHRtbA==">reactiveVal()</span>。我们将在第 16 章中回到 <code>reactiveVal()</code> ，但我想在这里展示它，因为它是一种非常有用的技术。你可能需要在阅读了那章之后重新阅读这一节，但即使没有所有的理论，你也会对潜在的应用有所了解。</p><p>正如你可能从名字中猜到的那样， <code>reactiveVal()</code> 非常类似于 <code>reactive()</code> 。通过调用带有初始值的 <code>reactiveVal()</code> 来创建反应性值，并以与反应性相同的方式检索该值：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>val <span class="token operator">&lt;-</span> reactiveVal<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre>val<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token comment">### #> [1] 10</span></pre></td></tr></table></figure><p>最大的区别是，你也可以更新一个响应式值，并且引用该值的所有反应式使用者都将重新计算。响应式值使用特殊的语法进行更新 —— 你像调用函数一样调用它，第一个参数是新的值：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>val<span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre>val<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token comment">#> [1] 20</span></pre></td></tr></table></figure><p>这意味着使用当前值更新反应值看起来像这样：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>val<span class="token punctuation">(</span>val<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre>val<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token comment">#> [1] 21</span></pre></td></tr></table></figure><p>不幸的是，如果你真的想在控制台中运行这段代码，你会得到一个错误，因为它必须在响应式环境中运行。这使得实验和调试更具挑战性，因为你需要 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3IvYmFzZS9icm93c2VyLmh0bWw=">browser()</span> 或类似方法来暂停 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2hpbnlBcHAuaHRtbA==">shinyApp()</span> 调用中的执行。这是我们将在第 16 章后面讨论的挑战之一。</p><p>现在，让我们把学习 <code>reactiveVal()</code> 的挑战放在一边，告诉你为什么你可能会烦恼。想象一下，您想要可视化单击与图上的点之间的距离。在下面的应用程序中，我们首先创建一个反应值来存储这些距离，并使用一个常量对其进行初始化，该常量将在我们单击任何内容之前使用。然后，我们使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vb2JzZXJ2ZUV2ZW50Lmh0bWw=">observeEvent()</span> 来更新单击鼠标时的反应值，并使用 <code>ggplot</code> 可视化具有点大小的距离。总而言之，这看起来像下面的代码，结果如图 7.4 所示。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>set.seed<span class="token punctuation">(</span><span class="token number">1014</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre>df <span class="token operator">&lt;-</span> data.frame<span class="token punctuation">(</span>x <span class="token operator">=</span> rnorm<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">,</span> y <span class="token operator">=</span> rnorm<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre></pre></td></tr><tr><td data-num="4"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> click <span class="token operator">=</span> <span class="token string">"plot_click"</span><span class="token punctuation">,</span> <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="8"></td><td><pre>  dist <span class="token operator">&lt;-</span> reactiveVal<span class="token punctuation">(</span>rep<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> nrow<span class="token punctuation">(</span>df<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  observeEvent<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_click<span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>    dist<span class="token punctuation">(</span>nearPoints<span class="token punctuation">(</span>df<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_click<span class="token punctuation">,</span> allRows <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">,</span> addDist <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span><span class="token operator">$</span>dist_<span class="token punctuation">)</span>  </pre></td></tr><tr><td data-num="11"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>  </pre></td></tr><tr><td data-num="13"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="14"></td><td><pre>    df<span class="token operator">$</span>dist <span class="token operator">&lt;-</span> dist<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="15"></td><td><pre>    ggplot<span class="token punctuation">(</span>df<span class="token punctuation">,</span> aes<span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> size <span class="token operator">=</span> dist<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> </pre></td></tr><tr><td data-num="16"></td><td><pre>      geom_point<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> </pre></td></tr><tr><td data-num="17"></td><td><pre>      scale_size_area<span class="token punctuation">(</span>limits <span class="token operator">=</span> c<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">,</span> max_size <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">,</span> guide <span class="token operator">=</span> <span class="token keyword">NULL</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="18"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="19"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/28b14f04bca5f6a00be49c50bdc09220ff421283/059c4/images/action-graphics/modifying-size-1.png" alt="图 7.4 此应用使用 reactiveVal() 来存储到上次单击的点的距离，然后将其映射到点大小。在这里，我显示了单击最左侧的点的结果 See live at https://hadley.shinyapps.io/ms-modifying-size 。"></p><p>这里有两个重要的 ggplot2 技术需要注意：</p><ul><li>在绘制之前，我将距离添加到数据框中。我认为在可视化之前，将相关变量放在数据框中是一种很好的做法。</li><li>我为 <span class="exturl" data-url="aHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3NjYWxlX3NpemUuaHRtbA==">scale_size_area()</span> 设置了限制，以确保点击之间的尺寸具有可比性。为了找到正确的范围，我做了一些交互式实验，但如有需要，您可以计算出确切的细节（参见本章末尾的练习）。</li></ul><p>有一个更复杂的想法。我想用画笔逐步添加点到一个选择。在这里，我使用不同的颜色显示选择，但你可以想象许多其他的应用程序。为了使这个工作，我将 <code>reactiveVal()</code> 初始化为一个 <code>FALSE</code> 的向量，然后使用<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vYnJ1c2hlZFBvaW50cy5odG1s"> brushedPoints ()</span> 和 | 将画笔下的任何点添加到选择。为了给用户一种重新开始的方式，我双击重置选择。图 7.5 显示了运行应用程序的几个截图。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> brush <span class="token operator">=</span> <span class="token string">"plot_brush"</span><span class="token punctuation">,</span> dblclick <span class="token operator">=</span> <span class="token string">"plot_reset"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  selected <span class="token operator">&lt;-</span> reactiveVal<span class="token punctuation">(</span>rep<span class="token punctuation">(</span><span class="token boolean">FALSE</span><span class="token punctuation">,</span> nrow<span class="token punctuation">(</span>mtcars<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre></pre></td></tr><tr><td data-num="7"></td><td><pre>  observeEvent<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_brush<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    brushed <span class="token operator">&lt;-</span> brushedPoints<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> input<span class="token operator">$</span>plot_brush<span class="token punctuation">,</span> allRows <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span><span class="token operator">$</span>selected_</pre></td></tr><tr><td data-num="9"></td><td><pre>    selected<span class="token punctuation">(</span>brushed <span class="token operator">|</span> selected<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre>  observeEvent<span class="token punctuation">(</span>input<span class="token operator">$</span>plot_reset<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="12"></td><td><pre>    selected<span class="token punctuation">(</span>rep<span class="token punctuation">(</span><span class="token boolean">FALSE</span><span class="token punctuation">,</span> nrow<span class="token punctuation">(</span>mtcars<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="14"></td><td><pre></pre></td></tr><tr><td data-num="15"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="16"></td><td><pre>    mtcars<span class="token operator">$</span>sel <span class="token operator">&lt;-</span> selected<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="17"></td><td><pre>    ggplot<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> aes<span class="token punctuation">(</span>wt<span class="token punctuation">,</span> mpg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> </pre></td></tr><tr><td data-num="18"></td><td><pre>      geom_point<span class="token punctuation">(</span>aes<span class="token punctuation">(</span>colour <span class="token operator">=</span> sel<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span></pre></td></tr><tr><td data-num="19"></td><td><pre>      scale_colour_discrete<span class="token punctuation">(</span>limits <span class="token operator">=</span> c<span class="token punctuation">(</span><span class="token string">"TRUE"</span><span class="token punctuation">,</span> <span class="token string">"FALSE"</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="20"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="21"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/da63b234ad81bc5e1e592a904a1eaed0f4ee092d/794de/images/action-graphics/persistent-1.png" alt=""><br><img data-src="https://d33wubrfki0l68.cloudfront.net/8c5a7aead6640c2720f28c4d05925d3a29e92730/e8f2e/images/action-graphics/persistent-3.png" alt="图 7.5 此应用程序使画笔“持续”，因此拖动它会增加当前选择。"></p><p>再次，我设定了比例的限制，以确保图例（和颜色）在第一次点击后不会改变。</p><h3 id="716-互动限制"><a class="anchor" href="#716-互动限制">#</a> 7.1.6 互动限制</h3><p>在我们继续之前，了解交互式图中的基本数据流以了解其局限性非常重要。基本流程是这样的：</p><ul><li>JavaScript 捕获鼠标事件。</li><li>Shiny 将鼠标事件数据发送回 R，告诉应用程序输入已过时。</li><li>重新计算所有下游反应式使用者。</li><li><code>plotOutput()</code> 生成一个新的 PNG 并将其发送到浏览器。</li></ul><p>对于本地应用程序，瓶颈往往是绘制图表所花费的时间。根据图表的复杂程度，这可能需要几分之一秒的时间。但对于托管应用程序，您还必须考虑将事件从浏览器传输到 R 所需的时间，然后将渲染的图表从 R 传输回浏览器。</p><p>一般来说，这意味着不可能创建动作和响应被视为即时的 Shiny 应用程序（即绘图似乎与您的操作同时更新）。如果您需要这种速度，您必须在 JavaScript 中执行更多的计算。一种方法是使用一个封装了 JavaScript 图形库的 R 包。现在，在我写这本书的时候，我认为你会得到 <code>plotly</code> 包的最佳体验，正如 Carson Sievert 在《<span class="exturl" data-url="aHR0cHM6Ly9wbG90bHktci5jb20v">使用 R、plotly 和 shiny 进行基于 Web 的交互式数据可视化</span>》一书中所述。</p><h2 id="72-动态高度和宽度"><a class="anchor" href="#72-动态高度和宽度">#</a> 7.2 动态高度和宽度</h2><p>本章的其余部分不如交互式图形那么令人兴奋，但包含了一些重要的内容。</p><p>首先，可以使绘图大小具有反应性，因此宽度和高度会根据用户操作而变化。为此，向 <code>renderPlot()</code> 的 <code>width</code> 和 <code>height</code> 参数提供零参数函数，这些参数现在必须在 server 中定义，而不是在 UI 中定义，因为它们可以更改。这些函数不应有参数，并返回所需的大小（以像素为单位）。它们在反应式环境中进行评估，以便您可以动态地调整绘图的大小。</p><p>以下应用程序演示了基本思想。它提供了两个直接控制绘图大小的滑块。图 7.6 中显示了几个示例屏幕截图。请注意，当您调整绘图大小时，数据保持不变：您不会获得新的随机数。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  sliderInput<span class="token punctuation">(</span><span class="token string">"height"</span><span class="token punctuation">,</span> <span class="token string">"height"</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">,</span> max <span class="token operator">=</span> <span class="token number">500</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  sliderInput<span class="token punctuation">(</span><span class="token string">"width"</span><span class="token punctuation">,</span> <span class="token string">"width"</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">,</span> max <span class="token operator">=</span> <span class="token number">500</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">,</span> width <span class="token operator">=</span> <span class="token number">250</span><span class="token punctuation">,</span> height <span class="token operator">=</span> <span class="token number">250</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="7"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    width <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> input<span class="token operator">$</span>width<span class="token punctuation">,</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    height <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> input<span class="token operator">$</span>height<span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>    res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="12"></td><td><pre>      plot<span class="token punctuation">(</span>rnorm<span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">,</span> rnorm<span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>    <span class="token punctuation">&#125;</span></pre></td></tr><tr><td data-num="14"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="15"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><img data-src="https://d33wubrfki0l68.cloudfront.net/187b93086b15e4f5f6afe04cb609019d1a37b424/537a6/demos/action-graphics/resize-narrow.png" alt=""></td><td><img data-src="https://d33wubrfki0l68.cloudfront.net/46c07091eaf6a8cd82a342e6fc55692e54740b7c/d0566/demos/action-graphics/resize-wide.png" alt="图 7.6 您可以使绘图大小动态化，以便它响应用户操作。该图显示了更改宽度的效果。在 https://hadley.shinyapps.io/ms-resize 上查看演示。"></td></tr><tr><td>图 7.6 您可以使绘图大小动态化，以便它响应用户操作。该图显示了更改宽度的效果。</td><td>在 <span class="exturl" data-url="aHR0cHM6Ly9oYWRsZXkuc2hpbnlhcHBzLmlvL21zLXJlc2l6ZQ==">https://hadley.shinyapps.io/ms-resize</span> 上查看演示。</td></tr></tbody></table><p>在实际应用中，您将在 <code>width</code> 和 <code>height</code> 函数中使用更复杂的表达式。例如，如果您在 ggplot2 中使用分面图，则可以使用它来增加图的大小，以保持各个分面大小大致相同。</p><h2 id="73-图片"><a class="anchor" href="#73-图片">#</a> 7.3 图片</h2><p>如果要显示现有图像（而不是绘图），则可以使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vcmVuZGVySW1hZ2UuaHRtbA==">renderImage()</span> 。例如，您可能有一个要向用户显示的照片目录。以下应用通过展示可爱的小狗照片来说明 <code>renderImage()</code> 的基础知识。这些照片来自 <span class="exturl" data-url="aHR0cHM6Ly91bnNwbGFzaC5jb20v">https://unsplash.com</span> ，我最喜欢的免版税库存照片来源。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>puppies <span class="token operator">&lt;-</span> tibble<span class="token operator">::</span>tribble<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  <span class="token operator">~</span>breed<span class="token punctuation">,</span> <span class="token operator">~</span> id<span class="token punctuation">,</span> <span class="token operator">~</span>author<span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="3"></td><td><pre>  <span class="token string">"corgi"</span><span class="token punctuation">,</span> <span class="token string">"eoqnr8ikwFE"</span><span class="token punctuation">,</span><span class="token string">"alvannee"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  <span class="token string">"labrador"</span><span class="token punctuation">,</span> <span class="token string">"KCdYn0xu2fU"</span><span class="token punctuation">,</span> <span class="token string">"shaneguymon"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  <span class="token string">"spaniel"</span><span class="token punctuation">,</span> <span class="token string">"TzjMd7i5WQI"</span><span class="token punctuation">,</span> <span class="token string">"_redo_"</span></pre></td></tr><tr><td data-num="6"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre></pre></td></tr><tr><td data-num="8"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  selectInput<span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">,</span> <span class="token string">"Pick a breed"</span><span class="token punctuation">,</span> choices <span class="token operator">=</span> setNames<span class="token punctuation">(</span>puppies<span class="token operator">$</span>id<span class="token punctuation">,</span> puppies<span class="token operator">$</span>breed<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  htmlOutput<span class="token punctuation">(</span><span class="token string">"source"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="11"></td><td><pre>  imageOutput<span class="token punctuation">(</span><span class="token string">"photo"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="14"></td><td><pre>  output<span class="token operator">$</span>photo <span class="token operator">&lt;-</span> renderImage<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="15"></td><td><pre>    list<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="16"></td><td><pre>      src <span class="token operator">=</span> file.path<span class="token punctuation">(</span><span class="token string">"puppy-photos"</span><span class="token punctuation">,</span> paste0<span class="token punctuation">(</span>input<span class="token operator">$</span>id<span class="token punctuation">,</span> <span class="token string">".jpg"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="17"></td><td><pre>      contentType <span class="token operator">=</span> <span class="token string">"image/jpeg"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="18"></td><td><pre>      width <span class="token operator">=</span> <span class="token number">500</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="19"></td><td><pre>      height <span class="token operator">=</span> <span class="token number">650</span></pre></td></tr><tr><td data-num="20"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="21"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> deleteFile <span class="token operator">=</span> <span class="token boolean">FALSE</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="22"></td><td><pre>  </pre></td></tr><tr><td data-num="23"></td><td><pre>  output<span class="token operator">$</span>source <span class="token operator">&lt;-</span> renderUI<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="24"></td><td><pre>    info <span class="token operator">&lt;-</span> puppies<span class="token punctuation">[</span>puppies<span class="token operator">$</span>id <span class="token operator">==</span> input<span class="token operator">$</span>id<span class="token punctuation">,</span> <span class="token punctuation">,</span> drop <span class="token operator">=</span> <span class="token boolean">FALSE</span><span class="token punctuation">]</span></pre></td></tr><tr><td data-num="25"></td><td><pre>    HTML<span class="token punctuation">(</span>glue<span class="token operator">::</span>glue<span class="token punctuation">(</span>"<span class="token operator">&lt;</span>p<span class="token operator">></span></pre></td></tr><tr><td data-num="26"></td><td><pre>      <span class="token operator">&lt;</span>a href<span class="token operator">=</span><span class="token string">'https://unsplash.com/photos/&#123;info$id&#125;'</span><span class="token operator">></span>original<span class="token operator">&lt;</span><span class="token operator">/</span>a<span class="token operator">></span> by</pre></td></tr><tr><td data-num="27"></td><td><pre>      <span class="token operator">&lt;</span>a href<span class="token operator">=</span><span class="token string">'https://unsplash.com/@&#123;info$author&#125;'</span><span class="token operator">></span><span class="token punctuation">&#123;</span>info<span class="token operator">$</span>author<span class="token punctuation">&#125;</span><span class="token operator">&lt;</span><span class="token operator">/</span>a<span class="token operator">></span></pre></td></tr><tr><td data-num="28"></td><td><pre>    <span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">></span>"<span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="29"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="30"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/70de2ab74b8c9f3984ea503ef40af3930324c62a/43790/demos/action-graphics/puppies-corgi.png" alt="图 7.7 使用 renderImage() 显示小狗可爱图片的应用。在 https://hadley.shinyapps.io/ms-puppies 上查看演示。"><br><code>renderImage()</code> 需要返回一个列表。唯一关键的参数是 <code>src</code> ，一个指向图像文件的本地路径。此外，您还可以提供：</p><ul><li><p><code>content-type</code> ，它定义了图像的 MIME 类型。如果没有提供，Shiny 将从文件扩展名中猜测，因此只有在图像没有扩展名时才需要提供此内容。</p></li><li><p>图像的 <code>width</code> 和 <code>height</code> （如果已知）。</p></li><li><p>任何其他参数，如 <code>class</code> 或 <code>alt</code> ，都将作为属性添加到 HTML 中的 <code>&lt;img&gt;</code> 标记中。</p></li></ul><p>您还必须提供 <code>deleteFile</code> 参数。不幸的是， <code>renderImage()</code> 最初是设计用于处理临时文件的，因此在渲染后会自动删除图像。这显然是非常危险的，因此在 Shiny 1.5.0 中改变了行为。现在 Shiny 不再删除图像，而是强制您明确选择想要的行为。</p><p>你可以在<br><span class="exturl" data-url="aHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS9hcnRpY2xlcy9pbWFnZXMuaHRtbA==">https://shiny.rstudio.com/articles/images.html</span><br>了解更多关于 <code>renderImage()</code> 的信息，并查看你可能使用它的其他方式。</p><h2 id="74-总结"><a class="anchor" href="#74-总结">#</a> 7.4 总结</h2><p>可视化是数据交流的强大方式，本章为您提供了几种高级技术来增强您的 Shiny 应用程序。接下来，您将学习向用户提供有关应用程序中正在发生的事情的反馈的技术，这对于需要花费大量时间的操作尤为重要。</p><h1 id="加关注"><a class="anchor" href="#加关注">#</a> 加关注</h1><p>关注公众号 “生信之巅”。</p><table align="center"><tr><td align="center"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/social/生信之巅公众号.jpg" alt="生信之巅微信公众号" style="width:100px;height:100px;vertical-align:-20px;border-radius:0;margin-right:0;margin-bottom:5px;align:center"></td><td align="center"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/social/小程序码.png" alt="生信之巅小程序码" style="width:100px;height:100px;vertical-align:-20px;border-radius:0;margin-left:0;margin-bottom:5px;align:center"></td></tr></table><p><font color="#FF0000"><ruby><b>敬告</b>：使用文中脚本请引用本文网址，请尊重本人的劳动成果，谢谢！<rt><b>Notice</b>: When you use the scripts in this article, please cite the link of this webpage. Thank you!</rt></ruby></font></p><div class="tags"><a href="/tags/%E7%BC%96%E7%A8%8B/" rel="tag"><i class="ic i-tag"></i> 编程</a> <a href="/tags/Shiny%E5%85%A5%E9%97%A8%E7%B3%BB%E5%88%97/" rel="tag"><i class="ic i-tag"></i> Shiny入门系列</a></div></div><footer><div class="meta"><span class="item"><span class="icon"><i class="ic i-calendar-check"></i> </span><span class="text">Edited on</span> <time title="Modified: 2024-01-25 09:16:52" itemprop="dateModified" datetime="2024-01-25T09:16:52+08:00">2024-01-25</time> </span><span id="post/6685.html" class="item leancloud_visitors" data-flag-title="Shiny从入门到入定——7-图形" title="Views"><span class="icon"><i class="ic i-eye"></i> </span><span class="text">Views</span> <span class="leancloud-visitors-count"></span> <span class="text">times</span></span></div><div class="reward"><button><i class="ic i-heartbeat"></i> Donate</button><p>Give me a cup of [coffee]~(￣▽￣)~*</p><div id="qr"><div><img data-src="/images/reward-wepays.jpg" alt="Hualin Liu WeChat Pay"><p>WeChat Pay</p></div><div><img data-src="/images/AliPays.jpg" alt="Hualin Liu Alipay"><p>Alipay</p></div></div></div><div id="copyright"><ul><li class="author"><strong>Post author: </strong>liaochenlanruo <i class="ic i-at"><em>@</em></i>了尘兰若的小坑</li><li class="link"><strong>Post link: </strong><a href="https://liaochenlanruo.gitee.io/post/6685.html" title="Shiny从入门到入定——7-图形">https://liaochenlanruo.gitee.io/post/6685.html</a></li><li class="license"><strong>Copyright Notice: </strong>All articles in this blog are licensed under <span class="exturl" data-url="aHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMC9kZWVkLnpo"><i class="ic i-creative-commons"><em>(CC)</em></i>BY-NC-SA</span> unless stating additionally.</li></ul></div></footer></article></div><div class="post-nav"><div class="item left"><a href="/post/6718.html" itemprop="url" rel="prev" data-background-image="https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;gh&#x2F;liaochenlanruo&#x2F;cdn@master&#x2F;img&#x2F;custom&#x2F;bgs&#x2F;thumb_206.webp" title="Shiny从入门到入定——6-布局、主题、HTML"><span class="type">Previous Post</span> <span class="category"><i class="ic i-flag"></i> IT</span><h3>Shiny从入门到入定——6-布局、主题、HTML</h3></a></div><div class="item right"><a href="/post/6561.html" itemprop="url" rel="next" data-background-image="https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;gh&#x2F;liaochenlanruo&#x2F;cdn@master&#x2F;img&#x2F;custom&#x2F;bgs&#x2F;thumb_208.webp" title="Shiny从入门到入定——8-用户反馈"><span class="type">Next Post</span> <span class="category"><i class="ic i-flag"></i> IT</span><h3>Shiny从入门到入定——8-用户反馈</h3></a></div></div><div class="wrap" id="comments"></div></div><div id="sidebar"><div class="inner"><div class="panels"><div class="inner"><div class="contents panel pjax" data-title="Contents"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#7-%E5%9B%BE%E5%BD%A2"><span class="toc-number">1.</span> <span class="toc-text">7 图形</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#71-%E4%BA%A4%E4%BA%92%E6%80%A7"><span class="toc-number">1.1.</span> <span class="toc-text">7.1 交互性</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#711-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86"><span class="toc-number">1.1.1.</span> <span class="toc-text">7.1.1 基础知识</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#712-%E7%82%B9%E5%87%BB"><span class="toc-number">1.1.2.</span> <span class="toc-text">7.1.2 点击</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#713-%E5%85%B6%E4%BB%96%E7%82%B9%E4%BA%8B%E4%BB%B6"><span class="toc-number">1.1.3.</span> <span class="toc-text">7.1.3 其他点事件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#714-%E5%88%B7%E6%B6%82brushing"><span class="toc-number">1.1.4.</span> <span class="toc-text">7.1.4 刷涂（Brushing）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#715-%E4%BF%AE%E6%94%B9%E7%BB%98%E5%9B%BE"><span class="toc-number">1.1.5.</span> <span class="toc-text">7.1.5 修改绘图</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#716-%E4%BA%92%E5%8A%A8%E9%99%90%E5%88%B6"><span class="toc-number">1.1.6.</span> <span class="toc-text">7.1.6 互动限制</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#72-%E5%8A%A8%E6%80%81%E9%AB%98%E5%BA%A6%E5%92%8C%E5%AE%BD%E5%BA%A6"><span class="toc-number">1.2.</span> <span class="toc-text">7.2 动态高度和宽度</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#73-%E5%9B%BE%E7%89%87"><span class="toc-number">1.3.</span> <span class="toc-text">7.3 图片</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#74-%E6%80%BB%E7%BB%93"><span class="toc-number">1.4.</span> <span class="toc-text">7.4 总结</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%8A%A0%E5%85%B3%E6%B3%A8"><span class="toc-number">2.</span> <span class="toc-text">加关注</span></a></li></ol></div><div class="related panel pjax" data-title="Related"><ul><li><a href="/post/10103.html" rel="bookmark" title="perl循环调用python爬虫批量下载喜马拉雅音频">perl循环调用python爬虫批量下载喜马拉雅音频</a></li><li><a href="/post/2159.html" rel="bookmark" title="syncthing搭建自己的同步云网盘">syncthing搭建自己的同步云网盘</a></li><li><a href="/post/50435.html" rel="bookmark" title="JAVA jre 安装或升级1603 error解决办法">JAVA jre 安装或升级1603 error解决办法</a></li><li><a href="/post/aa20.html" rel="bookmark" title="获取下一版本的内部预览版windows系统">获取下一版本的内部预览版windows系统</a></li><li><a href="/post/c78e.html" rel="bookmark" title="windows 10 中文乱码解决方案">windows 10 中文乱码解决方案</a></li><li><a href="/post/6bf1.html" rel="bookmark" title="Ubuntu open-mpi运行错误">Ubuntu open-mpi运行错误</a></li><li><a href="/post/f1a4.html" rel="bookmark" title="Github操作">Github操作</a></li><li><a href="/post/f298.html" rel="bookmark" title="Wget 技巧">Wget 技巧</a></li><li><a href="/post/16e1.html" rel="bookmark" title="Perl捕获外部命令执行异常并继续运行后续代码">Perl捕获外部命令执行异常并继续运行后续代码</a></li><li><a href="/post/9092.html" rel="bookmark" title="Perl获取外部命令执行结果的输出">Perl获取外部命令执行结果的输出</a></li><li><a href="/post/9d1b.html" rel="bookmark" title="Linux骚操作">Linux骚操作</a></li><li><a href="/post/3f45.html" rel="bookmark" title="Perl处理可恶的Windows换行符">Perl处理可恶的Windows换行符</a></li><li><a href="/post/893d.html" rel="bookmark" title="命令模式下配置Linux网络">命令模式下配置Linux网络</a></li><li><a href="/post/ed43.html" rel="bookmark" title="Linux中使用tar将大文件压缩为多个小的压缩包">Linux中使用tar将大文件压缩为多个小的压缩包</a></li><li><a href="/post/54a0.html" rel="bookmark" title="WSL安装Docker避坑指北">WSL安装Docker避坑指北</a></li><li><a href="/post/4b9c.html" rel="bookmark" title="Shiny从入门到入定——0欢迎入坑">Shiny从入门到入定——0欢迎入坑</a></li><li><a href="/post/b376.html" rel="bookmark" title="Shiny从入门到入定——1.在小小的花园里面挖呀挖呀挖">Shiny从入门到入定——1.在小小的花园里面挖呀挖呀挖</a></li><li><a href="/post/5369.html" rel="bookmark" title="Shiny从入门到入定——2-在大大的花园里面挖呀挖呀挖">Shiny从入门到入定——2-在大大的花园里面挖呀挖呀挖</a></li><li><a href="/post/41c3.html" rel="bookmark" title="Shiny从入门到入定——3-在特别大的花园里面挖呀挖呀挖">Shiny从入门到入定——3-在特别大的花园里面挖呀挖呀挖</a></li><li><a href="/post/377b.html" rel="bookmark" title="Shiny从入门到入定——4-挖坑完毕之案例研究">Shiny从入门到入定——4-挖坑完毕之案例研究</a></li><li><a href="/post/83c3.html" rel="bookmark" title="Shiny从入门到入定——5-工作流">Shiny从入门到入定——5-工作流</a></li><li><a href="/post/6718.html" rel="bookmark" title="Shiny从入门到入定——6-布局、主题、HTML">Shiny从入门到入定——6-布局、主题、HTML</a></li><li class="active"><a href="/post/6685.html" rel="bookmark" title="Shiny从入门到入定——7-图形">Shiny从入门到入定——7-图形</a></li><li><a href="/post/6561.html" rel="bookmark" title="Shiny从入门到入定——8-用户反馈">Shiny从入门到入定——8-用户反馈</a></li><li><a href="/post/72d6.html" rel="bookmark" title="Shiny从入门到入定——9-上传和下载">Shiny从入门到入定——9-上传和下载</a></li><li><a href="/post/e6be.html" rel="bookmark" title="Shiny从入门到入定——10-动态UI">Shiny从入门到入定——10-动态UI</a></li><li><a href="/post/8eca.html" rel="bookmark" title="Shiny从入门到入定——11-书签">Shiny从入门到入定——11-书签</a></li><li><a href="/post/3709.html" rel="bookmark" title="Shiny从入门到入定——12-Tidy evaluation">Shiny从入门到入定——12-Tidy evaluation</a></li><li><a href="/post/5e3d.html" rel="bookmark" title="Shiny从入门到入定——13-Why reactivity?">Shiny从入门到入定——13-Why reactivity?</a></li><li><a href="/post/43fc.html" rel="bookmark" title="深入理解特征标准化：为何、如何及其重要性">深入理解特征标准化：为何、如何及其重要性</a></li></ul></div><div class="overview panel" data-title="Overview"><div class="author" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="image" itemprop="image" alt="Hualin Liu" data-src="/images/head.jpg"><p class="name" itemprop="name">Hualin Liu</p><div class="description" itemprop="description">分享微生物生物信息学分析方法，欢迎加入QQ群交流945751012，不接受群内广告！</div></div><nav class="state"><div class="item posts"><a href="/archives/"><span class="count">130</span> <span class="name">posts</span></a></div><div class="item categories"><a href="/categories/"><span class="count">12</span> <span class="name">categories</span></a></div><div class="item tags"><a href="/tags/"><span class="count">54</span> <span class="name">tags</span></a></div></nav><div class="social"><span class="exturl item github" data-url="aHR0cDovL2dpdGh1Yi5jb20vbGlhb2NoZW5sYW5ydW8=" title="http:&#x2F;&#x2F;github.com&#x2F;liaochenlanruo"><i class="ic i-github"></i></span> <span class="exturl item zhihu" data-url="aHR0cHM6Ly93d3cuemhpaHUuY29tL3Blb3BsZS9zdWFuLWxhLW1pYW4tcGlhbi10YW5nLWNpdW0=" title="https:&#x2F;&#x2F;www.zhihu.com&#x2F;people&#x2F;suan-la-mian-pian-tang-cium"><i class="ic i-zhihu"></i></span> <span class="exturl item weibo" data-url="aHR0cHM6Ly93ZWliby5jb20vdS8yNzE1MjEwOTIz" title="https:&#x2F;&#x2F;weibo.com&#x2F;u&#x2F;2715210923"><i class="ic i-weibo"></i></span> <span class="exturl item about" data-url="aHR0cHM6Ly93d3cubGlhb2NoZW5sYW5ydW8uZnVuL2Fib3V0" title="https:&#x2F;&#x2F;www.liaochenlanruo.fun&#x2F;about"><i class="ic i-address-card"></i></span> <span class="exturl item email" data-url="bWFpbHRvOmxpYW9jaGVubGFucnVvQHdlYm1haWwuaHphdS5lZHUuY24=" title="mailto:liaochenlanruo@webmail.hzau.edu.cn"><i class="ic i-envelope"></i></span> <span class="exturl item douban" data-url="aHR0cHM6Ly93d3cuZG91YmFuLmNvbS9wZW9wbGUvbGlhb2NoZW5sYW5ydW8vP19pPTczNDYxMjVRalo1QjZWLw==" title="https:&#x2F;&#x2F;www.douban.com&#x2F;people&#x2F;liaochenlanruo&#x2F;?_i&#x3D;7346125QjZ5B6V&#x2F;"><i class="ic i-douban"></i></span> <span class="exturl item google" data-url="aHR0cHM6Ly9zY2hvbGFyLmdvb2dsZS5jby5qcC9jaXRhdGlvbnM/dXNlcj1YYW9STk1RQUFBQUomaGw9amE=" title="https:&#x2F;&#x2F;scholar.google.co.jp&#x2F;citations?user&#x3D;XaoRNMQAAAAJ&amp;hl&#x3D;ja"><i class="ic i-google"></i></span></div><ul class="menu"><li class="item"><a href="/" rel="section"><i class="ic i-home"></i>Home</a></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-user"></i>About</a><ul class="submenu"><li class="item"><a href="/about/" rel="section"><i class="ic i-user"></i>About me</a></li><li class="item"><a href="/comment/" rel="section"><i class="ic i-envelope"></i>Comment</a></li></ul></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-feather"></i>Posts</a><ul class="submenu"><li class="item"><a href="/archives/" rel="section"><i class="ic i-list-alt"></i>Archives</a></li><li class="item"><a href="/categories/" rel="section"><i class="ic i-th"></i>Categories</a></li><li class="item"><a href="/tags/" rel="section"><i class="ic i-tags"></i>Tags</a></li></ul></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-list-ol"></i>List</a><ul class="submenu"><li class="item"><a href="/photos/" rel="section"><i class="ic i-person"></i>Photos</a></li><li class="item"><a href="/skip/gallery/" rel="section"><i class="ic i-cloud"></i>Gallery</a></li><li class="item"><a href="/skip/box/" rel="section"><i class="ic i-magic"></i>Box</a></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly9saWFvY2hlbmxhbnJ1by5mdW4vcmVmZXJlbmNlLw=="><i class="ic i-th"></i>cheatsheets</span></li></ul></li><li class="item"><a href="/donate/" rel="section"><i class="ic i-coffee"></i>Donate</a></li><li class="item"><a href="/friends/" rel="section"><i class="ic i-heart"></i>Friends</a></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly9saWFvY2hlbmxhbnJ1by5naXRodWIuaW8="><i class="ic i-external-link-alt"></i>中文版</span></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly90cmF2ZWxsaW5ncy5saW5r"><i class="ic i-forward"></i>Travelling</span></li></ul></div></div></div><ul id="quick"><li class="prev pjax"><a href="/post/6718.html" rel="prev" title="Previous Post"><i class="ic i-chevron-left"></i></a></li><li class="up"><i class="ic i-arrow-up"></i></li><li class="down"><i class="ic i-arrow-down"></i></li><li class="next pjax"><a href="/post/6561.html" rel="next" title="Next Post"><i class="ic i-chevron-right"></i></a></li><li class="percent"></li></ul></div></div><div class="dimmer"></div></div></main><footer id="footer"><div class="inner"><div class="widgets"></div><div class="status"><div class="copyright">&copy; 2018 – <span itemprop="copyrightYear">2024</span> <span class="with-love"><i class="ic i-sakura rotate"></i> </span><span class="author" itemprop="copyrightHolder">Hualin Liu @ ResearchGo</span></div><div class="count"><span class="post-meta-item-icon"><i class="ic i-chart-area"></i> </span><span title="Symbols count total">788k words</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-coffee"></i> </span><span title="Reading time total">11:57</span><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-info-circle"></i> </span><span style="padding-left:1px"><span id="busuanzi_container_site_pv">Total visits: <span id="busuanzi_value_site_pv" style="color:#f99"></span> times</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-user"></i> </span><span style="padding-left:1px"><span id="busuanzi_container_site_uv">Total visitors: <span id="busuanzi_value_site_uv" style="color:#f99"></span> people</span></span></span></div><div class="powered-by">Powered by <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlv">Hexo</span> & Theme.<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2FtZWhpbWUvaGV4by10aGVtZS1zaG9rYQ==">Shoka</span></div></div></div></footer></div><script data-config type="text/javascript">var LOCAL={path:"post/6685.html",favicon:{show:"（●´3｀●）Goooood",hide:"(´Д｀)Booooom"},search:{placeholder:"Search for Posts",empty:"We didn't find any results for the search: ${query}",stats:"${hits} results found in ${time} ms"},valine:!0,fancybox:!0,copyright:'Copied to clipboard successfully! <br> All articles in this blog are licensed under <i class="ic i-creative-commons"></i>BY-NC-SA.',ignores:[function(e){return e.includes("#")},function(e){return new RegExp(LOCAL.path+"$").test(e)}]}</script><script src="https://cdn.polyfill.io/v2/polyfill.js"></script><script src="//cdn.jsdelivr.net/combine/npm/pace-js@1.0.2/pace.min.js,npm/pjax@0.2.8/pjax.min.js,npm/whatwg-fetch@3.4.0/dist/fetch.umd.min.js,npm/animejs@3.2.0/lib/anime.min.js,npm/algoliasearch@4/dist/algoliasearch-lite.umd.js,npm/instantsearch.js@4/dist/instantsearch.production.min.js,npm/lozad@1/dist/lozad.min.js,npm/quicklink@2/dist/quicklink.umd.js"></script><script src="/js/app.js?v=0.2.5"></script><script data-pjax>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?d211830a796ceefb38a141fde14e4d5a";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script></body></html>